import Formatter from '../core/Formatter';
import Tokenizer from '../core/Tokenizer';

const reservedWords = [
  'ALL',
  'ALTER',
  'ANALYZE',
  'AND',
  'ANY',
  'ARRAY',
  'AS',
  'ASC',
  'BEGIN',
  'BETWEEN',
  'BINARY',
  'BOOLEAN',
  'BREAK',
  'BUCKET',
  'BUILD',
  'BY',
  'CALL',
  'CASE',
  'CAST',
  'CLUSTER',
  'COLLATE',
  'COLLECTION',
  'COMMIT',
  'CONNECT',
  'CONTINUE',
  'CORRELATE',
  'COVER',
  'CREATE',
  'DATABASE',
  'DATASET',
  'DATASTORE',
  'DECLARE',
  'DECREMENT',
  'DELETE',
  'DERIVED',
  'DESC',
  'DESCRIBE',
  'DISTINCT',
  'DO',
  'DROP',
  'EACH',
  'ELEMENT',
  'ELSE',
  'END',
  'EVERY',
  'EXCEPT',
  'EXCLUDE',
  'EXECUTE',
  'EXISTS',
  'EXPLAIN',
  'FALSE',
  'FETCH',
  'FIRST',
  'FLATTEN',
  'FOR',
  'FORCE',
  'FROM',
  'FUNCTION',
  'GRANT',
  'GROUP',
  'GSI',
  'HAVING',
  'IF',
  'IGNORE',
  'ILIKE',
  'IN',
  'INCLUDE',
  'INCREMENT',
  'INDEX',
  'INFER',
  'INLINE',
  'INNER',
  'INSERT',
  'INTERSECT',
  'INTO',
  'IS',
  'JOIN',
  'KEY',
  'KEYS',
  'KEYSPACE',
  'KNOWN',
  'LAST',
  'LEFT',
  'LET',
  'LETTING',
  'LIKE',
  'LIMIT',
  'LSM',
  'MAP',
  'MAPPING',
  'MATCHED',
  'MATERIALIZED',
  'MERGE',
  'MISSING',
  'NAMESPACE',
  'NEST',
  'NOT',
  'NULL',
  'NUMBER',
  'OBJECT',
  'OFFSET',
  'ON',
  'OPTION',
  'OR',
  'ORDER',
  'OUTER',
  'OVER',
  'PARSE',
  'PARTITION',
  'PASSWORD',
  'PATH',
  'POOL',
  'PREPARE',
  'PRIMARY',
  'PRIVATE',
  'PRIVILEGE',
  'PROCEDURE',
  'PUBLIC',
  'RAW',
  'REALM',
  'REDUCE',
  'RENAME',
  'RETURN',
  'RETURNING',
  'REVOKE',
  'RIGHT',
  'ROLE',
  'ROLLBACK',
  'SATISFIES',
  'SCHEMA',
  'SELECT',
  'SELF',
  'SEMI',
  'SET',
  'SHOW',
  'SOME',
  'START',
  'STATISTICS',
  'STRING',
  'SYSTEM',
  'THEN',
  'TO',
  'TRANSACTION',
  'TRIGGER',
  'TRUE',
  'TRUNCATE',
  'UNDER',
  'UNION',
  'UNIQUE',
  'UNKNOWN',
  'UNNEST',
  'UNSET',
  'UPDATE',
  'UPSERT',
  'USE',
  'USER',
  'USING',
  'VALIDATE',
  'VALUE',
  'VALUED',
  'VALUES',
  'VIA',
  'VIEW',
  'WHEN',
  'WHERE',
  'WHILE',
  'WITH',
  'WITHIN',
  'WORK',
  'XOR',
];

const reservedTopLevelWords = [
  'DELETE FROM',
  'EXCEPT ALL',
  'EXCEPT',
  'EXPLAIN DELETE FROM',
  'EXPLAIN UPDATE',
  'EXPLAIN UPSERT',
  'FROM',
  'GROUP BY',
  'HAVING',
  'INFER',
  'INSERT INTO',
  'LET',
  'LIMIT',
  'MERGE',
  'NEST',
  'ORDER BY',
  'PREPARE',
  'SELECT',
  'SET CURRENT SCHEMA',
  'SET SCHEMA',
  'SET',
  'UNNEST',
  'UPDATE',
  'UPSERT',
  'USE KEYS',
  'VALUES',
  'WHERE',
];

const reservedTopLevelWordsNoIndent = ['INTERSECT', 'INTERSECT ALL', 'MINUS', 'UNION', 'UNION ALL'];

const reservedNewlineWords = [
  'AND',
  'OR',
  'XOR',
  // joins
  'JOIN',
  'INNER JOIN',
  'LEFT JOIN',
  'LEFT OUTER JOIN',
  'RIGHT JOIN',
  'RIGHT OUTER JOIN',
];

// For reference: http://docs.couchbase.com.s3-website-us-west-1.amazonaws.com/server/6.0/n1ql/n1ql-language-reference/index.html
export default class N1qlFormatter extends Formatter {
  tokenizer() {
    return new Tokenizer({
      reservedWords,
      reservedTopLevelWords,
      reservedNewlineWords,
      reservedTopLevelWordsNoIndent,
      stringTypes: [`""`, "''", '``'],
      openParens: ['(', '[', '{'],
      closeParens: [')', ']', '}'],
      namedPlaceholderTypes: ['$'],
      lineCommentTypes: ['#', '--'],
      operators: ['==', '!='],
    });
  }
}
